package core;

import java.util.List;
import java.util.LinkedList;

/**
 * A <code>GameObject</code> represents an object in a game instance that clients
 * can manipulate (by sending commands to the server). Each <code>GameObject</code>
 * has a name and zero or more <code>Attribute</code>s.<br><br>
 * 
 * In addition, <code>GameObject</code> implements the Composite pattern: each
 * object in the game may contain zero or more "child" <code>GameObject</code>s.
 * There are no methods to add generic children directly, however; each subclass
 * that contains specific types of children is responsible for keeping track of
 * its own children. In addition, subclasses that contain such lists of children
 * should call <code>childrens.add</code> to hook their child lists into the
 * Composite structure.
 */
public abstract class GameObject
{
	/**
	 * Construct a new GameObject with a textual identifier.
	 * @param name the name
	 */
	public GameObject(String name) {
		this.name = name;
		childrens.add(java.util.Collections.unmodifiableList(attributes));
	}

	/**
	 * Add an Attribute to this GameObject. This method may throw
	 * <code>UnsupportedOperationException</cdoe> in subclasses of
	 * <code>GameObject</code> (see <code>Attribute</code>).
	 * @param a the Attribute to add
	 * @return the Attribute added
	 */
	public Attribute addAttribute(Attribute<?> a) {
		attributes.add(a);
		a.parent = this;
		return a;
	}

	public boolean removeAttribute(Attribute<?> a) {
		if (attributes.remove(a)) {
			a.parent = null;
			return true;
		}
		return false;
	}

	/**
	 * Returns an unmodifiable list of attributes for this GameObject
	 */
	public List<Attribute> getAttributes() {
		return java.util.Collections.unmodifiableList(attributes);
	}

	public void setAttributes(List<Attribute> attributes) {
		for (Attribute<?> a : this.attributes)
			a.parent = null;
		this.attributes.clear();
		this.attributes.addAll(attributes);
		for (Attribute<?> a : attributes)
			a.parent = this;
	}

	/**
	 * Returns the identifier of this GameObject
	 * @return the textual identifier
	 */
	public String getName() {
		return name;
	}

	/**
	 * Sets the name of this GameObject
	 * @param name a textual identifier
	 */
	public void setName(String name) {
		this.name = name;
		notifyObservers();
	}

	public List<java.util.Collection<? extends GameObject>> getChildrens() {
		return java.util.Collections.unmodifiableList(childrens);
	}

	public String toString() {
		return name;
	}

	/**
	 * Adds a GameObjectObserver to be notified of state changes on this GameObject
	 */
	public void addObserver(GameObjectObserver observer) {
		observers.add(observer);
	}

	/**
	 * Causes all GameObjectObservers for this GameObject to be notified that a
	 * state change has occured
	 */
	protected void notifyObservers() {
		for (GameObjectObserver observer : observers)
			observer.update();
	}

	/** A List of Collections of all children of this GameObject. This allows us to
	 * track changes to each child list automatically, and avoids duplicating references. */
	protected final List<java.util.Collection<? extends GameObject>> childrens = new LinkedList<java.util.Collection<? extends GameObject>>();
	private final List<GameObjectObserver> observers = new LinkedList<GameObjectObserver>();
	protected final List<Attribute> attributes = new LinkedList<Attribute>();
	protected String name;
}